package com.example.administrator.myapplication.net;

import android.util.Log;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ConnectionPool {
    String tag = "ConnectionPool";
    private long keepAlive;
    private boolean isCleanUpRuning;
    private Deque<HttpConnection> connections = new ArrayDeque<>();
    private Runnable cleanUpRunable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                long waitDuration = cleanUp(System.currentTimeMillis());
                if (waitDuration < -1) {
                    return;
                }
                synchronized (ConnectionPool.this){
                    try {
                        ConnectionPool.this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    };

    private long cleanUp(long now) {
        long longestIdeaDuration = -1;
        synchronized (this) {
            Iterator<HttpConnection> iterator = connections.iterator();
            while (iterator.hasNext()) {
                HttpConnection connection = iterator.next();
                long ideaDuration = now - connection.getLastUseTime();
                if (ideaDuration > keepAlive) {
                    iterator.remove();
                    Log.e(tag, "超过限制时间，移除连接池");
                    connection.close();
                    continue;
                }
                if (longestIdeaDuration < ideaDuration) {
                    longestIdeaDuration = ideaDuration;
                }
            }
            if (longestIdeaDuration >= 0) {
                return keepAlive - longestIdeaDuration;
            }
            isCleanUpRuning = false;
            return longestIdeaDuration;
        }
    }

    private static Executor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L,
            TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, "Connection pool");
            thread.setDaemon(true);
            return thread;
        }
    });

    public ConnectionPool(long keepAlive, TimeUnit unit) {
        this.keepAlive = unit.toMillis(keepAlive);
    }

    public void put(HttpConnection connection) {
        if (isCleanUpRuning) {
            isCleanUpRuning = true;
            executor.execute(cleanUpRunable);
        }
        connections.add(connection);
    }

    public HttpConnection get(String host, int port) {
        Iterator<HttpConnection> iterator = connections.iterator();
        while (iterator.hasNext()) {
            HttpConnection connection = iterator.next();
            if (connection.isSameAddress(host, port)) {
                iterator.remove();
                return connection;
            }
        }
        return null;
    }
}
